package cn.imu.Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public abstract  class RSACoder extends Coder{

    public static final String KEY_ALGORITHM="RSA";
    public static final String SIGNATURE_ALGORITHM="MD5withRSA";

    private static final String PUBLIC_KEY="RSAPublicKey";
    private static final String PRIVATE_KEY="RSAPrivateKey";

    /*
    在传输过程中，使用字符串传输，用的时候需要从字符串解密为原始公钥
    公钥加密
     */
    public static byte[] encryptByPublicKey(byte[] data,String key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        //对公钥解密
        byte[] keyBytes=decryptBASE64(key);
        //取得公钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        //对数据加密---公钥加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);
        return cipher.doFinal(data);


    }
    /*私钥解密
    * */
    public static byte[] decryptByPrivateKey(byte[] data,String key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        //对密钥解密
        byte[] keyBytes=decryptBASE64(key);
        //取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,privateKey);
        return cipher.doFinal(data);

    }

    /*
    BASE64编码
     */
    public static String encryptBASE64(byte[] key){
        return (new BASE64Encoder()).encodeBuffer(key);
    }
    /*
    取得公钥
     */
    public static String getPublicKey(Map<String,Object> keyMap){
        Key key=(Key) keyMap.get(PUBLIC_KEY);
        return encryptBASE64(key.getEncoded());
    }
    /*
    初始化密钥
     */
    public static Map<String,Object> initKey() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGen= KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);

        KeyPair keyPair = keyPairGen.generateKeyPair();

        //公钥
        RSAPrivateKey publicKey=(RSAPrivateKey) keyPair.getPublic();

        //私钥
        RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();

        Map<String,Object> keyMap=new HashMap<String,Object>(2);
        keyMap.put(PUBLIC_KEY,publicKey);
        keyMap.put(PRIVATE_KEY,privateKey);
        return keyMap;
    }

    /*
    私钥签名
     */
    public static String sign(byte[] data,String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        //解密由base64编码的私钥
        byte[] keyBytes=decryptBASE64(privateKey);

        //构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(keyBytes);

        //KEY_ALGORITHM指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //取私钥对象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(priKey);
        signature.update(data);

        return encryptBASE64(signature.sign());

    }

    /*
    校验签名
    成功返回true,失败返回false
     */
    public static boolean verify(byte[] data,String publicKey,String sign) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        //解密由base64编码的私钥
        byte[] keyBytes=decryptBASE64(publicKey);
        //构造X509EncodedKeySpec对象
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        //KEY_ALGORITHM指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //取公钥对象
        PublicKey pubKey= keyFactory.generatePublic(x509EncodedKeySpec);

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(pubKey);
        signature.update(data);

        //验证签名是否正常
        return signature.verify(decryptBASE64(sign));
    }
}
